/*
 * Copyright 2020-2030, MateCloud, DAOTIANDI Technology Inc All rights reserved.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      https://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 * Author: pangu(7333791@qq.com)
 */
package com.yc.cloud.common.oss.controller;

import cn.hutool.core.util.StrUtil;
import com.yc.cloud.common.basic.api.ResponseResult;
import com.yc.cloud.common.basic.dto.BasePageReqDTO;
import com.yc.cloud.common.orm.CommonPage;
import com.yc.cloud.common.oss.common.OssErrorTips;
import com.yc.cloud.common.oss.request.*;
import com.yc.cloud.common.oss.service.OssFileService;
import com.yc.cloud.common.oss.vo.GetChunkVo;
import com.yc.cloud.common.oss.vo.OssFileVo;
import io.swagger.annotations.*;
import lombok.val;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import io.swagger.v3.oas.annotations.Hidden;

import java.security.Principal;

/**
 * <p>
 * 文件 前端控制器
 * </p>
 *
 * @author Yancy
 * @since 2023-12-25
 */
@RestController
@RequestMapping("/oss/files")
@Api(value = "文件接口", tags = "文件接口")
public class OssFileController {

    private final OssFileService ossFileService;

    public OssFileController(OssFileService ossFileService) {
        this.ossFileService = ossFileService;
    }

    @PostMapping
    @ApiOperation(value = "上传文件", notes = "添加")
    public ResponseResult<OssFileVo> upload(@RequestPart("file") MultipartFile file, Principal principal, @Validated OssUploadParam param) {
        //使用用户名作为存储桶名字
        if (principal != null) {
            param.setBucket(principal.getName());
        } else {
            param.setBucket("");
        }
        //如果没有指定父文件ID,则默认为0
        if (StrUtil.isEmpty(param.getParentFileId())) {
            param.setParentFileId("0");
        }
        val result = ossFileService.upload(file, param);
        return ResponseResult.success(result);
    }

    @PostMapping("/base64")
    @ApiOperation(value = "上传base64格式图片", notes = "接收base64编码的图片数据")
    public ResponseResult<OssFileVo> uploadBase64(@RequestBody @Validated OssUploadBase64Param param,
             Principal principal) {
        // 使用用户名作为存储桶名字
        if (principal != null) {
            param.setBucket(principal.getName());
        } else {
            param.setBucket("");
        }
        val result = ossFileService.uploadByBase64(param);
        return ResponseResult.success(result);
    }

    @GetMapping
    @ApiOperation(value = "文件列表", notes = "支持分页查询,字段(名称,文件标识)模糊匹配,排序等")
    public ResponseResult<CommonPage<OssFileVo>> list(@Validated OssListParam param, BasePageReqDTO queryParam) {
        val list = ossFileService.list(param, queryParam);
        return ResponseResult.success(CommonPage.restPage(list));
    }

    // private OssFileVoPro convertOssFileVoPro(OssFileVo ossFileVo) {
    // val vo = new OssFileVoPro();
    // BeanUtil.copyProperties(ossFileVo, vo);
    // val memberAccount = memberAccountService.getById(ossFileVo.getCreateBy());
    // vo.setMember(memberAccountService.convertVo(memberAccount));
    // return vo;
    // }

    @GetMapping("{fileid}")
    @ApiOperation(value = "文件详情", notes = "根据文件标识查询")
    public ResponseResult<OssFileVo> getByFileId(
            @PathVariable @ApiParam(value = "fileid", required = true) String fileid) {
        return ResponseResult.success(ossFileService.getByFileId(fileid));
    }

    @GetMapping("{fileid}/info")
    @ApiOperation(value = "文件详情(无token)", notes = "根据文件标识查询")
    public ResponseResult<OssFileVo> getByFileIdByNoToken(
            @PathVariable @ApiParam(value = "fileid", required = true) String fileid) {
        return ResponseResult.success(ossFileService.getByFileId(fileid));
    }

    // @ApiOperation(value = "删除文件", notes = "通过文件标识删除")
    // @DeleteMapping(value = "{fileid}")
    // public ResponseResult<Boolean> deleteByFileId(@PathVariable @ApiParam(value =
    // "fileid", required = true) String fileid) {
    // val ossFile = ossFileService.getByFileId(fileid);
    // if (ossFile == null) {
    // return ResponseResult.failed(TipsConstants.QUERY_EMPTY);
    // }
    // if (!Objects.equals(ossFile.getCreateBy(), MemberUtils.getCurrentUseId())) {
    // return ResponseResult.failed(TipsConstants.NO_PERMISSION);
    // }
    // val flag = ossFileService.deleteByFileId(fileid);
    // if (flag) {
    // return ResponseResult.success(true);
    // }
    // return ResponseResult.failed();
    // }

    // @PostMapping("move")
    // @ApiOperation(value = "移动文件到指定目录", notes = "支持多个文件移动到指定目录")
    // public ResponseResult<Boolean> moveFiles2Dir(@Validated @RequestBody
    // OssFileMove2DirParam param) {
    // val result = ossFileService.moveFiles2Dir(param);
    // return result ? ResponseResult.success(true) : ResponseResult.failed();
    // }

    @PostMapping("uploadChunk")
    @ApiOperation(value = "分块上传文件", notes = "将大文件拆分成多个小块上传,第一块chunkNumberk传1")
    public ResponseResult<Boolean> uploadChunk(OssUploadChunkParam param, @RequestPart("file") MultipartFile file,
             Principal principal) {
        // 使用用户名作为存储桶名字
        if (param.getChunkNumber() > param.getTotalChunkNumber()) {
            return ResponseResult.failed(OssErrorTips.CHUNK_NUMBER_ERROR);
        }
        if (principal != null) {
            param.setBucket(principal.getName());
        } else {
            param.setBucket("");
        }
        val result = ossFileService.uploadChunk(file, param);
        return result ? ResponseResult.success(true) : ResponseResult.failed();
    }

    @GetMapping("getChunk")
    @ApiOperation(value = "获取当前文件上传块数", notes = "文件从当前块数后继续上传")
    public ResponseResult<GetChunkVo> getChunk(@Validated OssGetChunkParam param,  Principal principal) {
        //使用用户名作为存储桶名字
        if (principal != null) {
            param.setBucket(principal.getName());
        } else {
            param.setBucket("");
        }
        val result = ossFileService.getChunk(param);
        return result != null ? ResponseResult.success(result) : ResponseResult.failed();
    }

    // @ApiOperation(value = "合并分块文件", notes = "通过ID修改")
    // @PostMapping(value = "merge")
    // public ResponseResult<Long> merge(@Validated @RequestBody OssMergeParam
    // param, @Hidden Principal principal) {
    // param.setBucket(principal.getName());
    // val mergeFileName = param.getFileId() + "." + param.getSuffix();
    // val mergePath = Paths.get(PathUtils.getBasePath(), param.getBucket(),
    // mergeFileName);
    // val result = ossFileService.mergeFileChunks(mergePath, param.getBucket(),
    // param.getFileId());
    // if (result) {
    // return ResponseResult.success();
    // }
    // return ResponseResult.failed();
    // }

    @PostMapping("dir/create")
    @ApiOperation(value = "创建目录", notes = "如果创建的是顶层目录,没有父目录ID,则parentId传0")
    public ResponseResult<OssFileVo> createDir(@Validated @RequestBody OssCreateDirParam param) {
        val result = ossFileService.createDir(param);
        return result != null ? ResponseResult.success(result) : null;
    }

    @PostMapping("dir/{fileid}/update")
    @ApiOperation(value = "修改目录", notes = "如果创建的是顶层目录,没有父目录ID,则parentId传0")
    public ResponseResult<OssFileVo> updateDir(@Validated @RequestBody OssUpdateDirParam param,
            @PathVariable @ApiParam(value = "fileid", required = true) String fileid) {
        val result = ossFileService.updateDir(fileid, param);
        return result != null ? ResponseResult.success(result) : null;
    }

    @ApiOperation(value = "修改文件信息", notes = "通过ID修改")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "fileid", required = true, value = "fileid", paramType = "path", dataTypeClass = Long.class), })
    @PutMapping(value = "{fileid}")
    public ResponseResult<Long> update(@PathVariable String fileid, @Validated @RequestBody OssUpdateParam param) {
        val result = ossFileService.updateByFileId(fileid, param);
        if (result) {
            return ResponseResult.success();
        }
        return ResponseResult.failed();
    }

    @ApiOperation(value = "修改文件封面", notes = "通过ID修改")
    @PutMapping(value = "{fileid}/cover")
    public ResponseResult<Long> updateCover(@PathVariable String fileid, @RequestPart("file") MultipartFile file,
             Principal principal) {
        val param = new OssUpdateCoverParam();
        param.setBucket(principal.getName());
        val result = ossFileService.updateCover(fileid, file, param);
        if (result) {
            return ResponseResult.success();
        }
        return ResponseResult.failed();
    }
}
